// ==================== 安全防护工具 ====================
/**
 * 安全防护工具模块
 * @description 提供XSS防护、CSRF防护、输入验证等安全功能
 */

import DOMPurify from 'dompurify'

// ==================== XSS防护 ====================

/**
 * XSS防护配置
 * @description 定义DOMPurify的配置选项，用于HTML内容净化
 */
const XSS_CONFIG = {
    ALLOWED_TAGS: [
        'p', 'br', 'strong', 'em', 'u', 's', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
        'ul', 'ol', 'li', 'blockquote', 'code', 'pre', 'a', 'img', 'table', 'tr', 'td', 'th',
        'div', 'span', 'mark', 'del', 'ins', 'sub', 'sup'
    ],
    ALLOWED_ATTR: [
        'href', 'src', 'alt', 'title', 'target', 'rel', 'class', 'id', 'style',
        'width', 'height', 'data-*'
    ],
    ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i
}

/**
 * 净化HTML内容，防止XSS攻击
 * @param html 需要净化的HTML字符串
 * @param config 净化配置，可选
 * @returns 净化后的安全HTML字符串
 * @example
 * const safeHtml = sanitizeHtml('<script>alert("xss")</script><p>安全内容</p>')
 * // 返回: '<p>安全内容</p>'
 */
export const sanitizeHtml = (html: string, config?: any): string => {
    if (!html || typeof html !== 'string') {
        return ''
    }

    const sanitizeConfig = {
        ...XSS_CONFIG,
        ...config
    }

    return DOMPurify.sanitize(html, sanitizeConfig).toString()
}

/**
 * 验证和净化用户输入
 * @param input 用户输入的内容
 * @param type 输入类型：'text' | 'html' | 'url' | 'email'
 * @returns 净化后的安全内容
 * @example
 * const safeInput = validateInput('<script>alert("xss")</script>', 'html')
 * // 返回净化后的内容
 */
export const validateInput = (input: string, type: 'text' | 'html' | 'url' | 'email' = 'text'): string => {
    if (!input || typeof input !== 'string') {
        return ''
    }

    switch (type) {
        case 'html':
            return sanitizeHtml(input)
        case 'url':
            return validateUrl(input)
        case 'email':
            return validateEmail(input)
        case 'text':
        default:
            return escapeHtml(input)
    }
}

/**
 * 转义HTML特殊字符
 * @param text 需要转义的文本
 * @returns 转义后的安全文本
 * @example
 * const safeText = escapeHtml('<script>alert("xss")</script>')
 * // 返回: '&lt;script&gt;alert("xss")&lt;/script&gt;'
 */
export const escapeHtml = (text: string): string => {
    if (!text || typeof text !== 'string') {
        return ''
    }

    return text
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#x27;')
        .replace(/\//g, '&#x2F;')
}

/**
 * 验证URL格式
 * @param url 需要验证的URL
 * @returns 验证通过返回原URL，否则返回空字符串
 * @example
 * const safeUrl = validateUrl('https://example.com')
 * // 返回: 'https://example.com'
 */
export const validateUrl = (url: string): string => {
    if (!url || typeof url !== 'string') {
        return ''
    }

    try {
        const urlObj = new URL(url)
        const allowedProtocols = ['http:', 'https:', 'mailto:', 'tel:']

        if (!allowedProtocols.includes(urlObj.protocol)) {
            return ''
        }

        return url
    } catch {
        return ''
    }
}

/**
 * 验证邮箱格式
 * @param email 需要验证的邮箱
 * @returns 验证通过返回原邮箱，否则返回空字符串
 * @example
 * const safeEmail = validateEmail('user@example.com')
 * // 返回: 'user@example.com'
 */
export const validateEmail = (email: string): string => {
    if (!email || typeof email !== 'string') {
        return ''
    }

    const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
    return emailRegex.test(email) ? email : ''
}

// ==================== CSRF防护 ====================

/**
 * CSRF Token管理
 * @description 生成、存储和验证CSRF Token
 */
class CSRFProtection {
    private tokenKey = 'csrf_token'
    private tokenExpiryKey = 'csrf_token_expiry'
    private tokenExpiryTime = 24 * 60 * 60 * 1000 // 24小时

    /**
     * 生成CSRF Token
     * @returns 生成的Token字符串
     */
    generateToken(): string {
        const token = this.generateRandomToken()
        const expiry = Date.now() + this.tokenExpiryTime

        localStorage.setItem(this.tokenKey, token)
        localStorage.setItem(this.tokenExpiryKey, expiry.toString())

        return token
    }

    /**
     * 获取当前有效的CSRF Token
     * @returns Token字符串，如果过期或不存在则返回空字符串
     */
    getToken(): string {
        const token = localStorage.getItem(this.tokenKey)
        const expiry = localStorage.getItem(this.tokenExpiryKey)

        if (!token || !expiry) {
            return ''
        }

        if (Date.now() > parseInt(expiry)) {
            this.clearToken()
            return ''
        }

        return token
    }

    /**
     * 验证CSRF Token
     * @param token 需要验证的Token
     * @returns 验证结果
     */
    validateToken(token: string): boolean {
        if (!token) {
            return false
        }

        const currentToken = this.getToken()
        return token === currentToken
    }

    /**
     * 清除CSRF Token
     */
    clearToken(): void {
        localStorage.removeItem(this.tokenKey)
        localStorage.removeItem(this.tokenExpiryKey)
    }

    /**
     * 生成随机Token
     * @returns 随机Token字符串
     */
    private generateRandomToken(): string {
        const array = new Uint8Array(32)
        crypto.getRandomValues(array)
        return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('')
    }
}

// 创建CSRF防护实例
export const csrfProtection = new CSRFProtection()

/**
 * 为请求添加CSRF Token
 * @param headers 请求头对象
 * @returns 添加了CSRF Token的请求头
 * @example
 * const headers = addCSRFToken({ 'Content-Type': 'application/json' })
 * // 返回: { 'Content-Type': 'application/json', 'X-CSRF-Token': 'token...' }
 */
export const addCSRFToken = (headers: Record<string, string> = {}): Record<string, string> => {
    const token = csrfProtection.getToken()
    if (token) {
        headers['X-CSRF-Token'] = token
    }
    return headers
}

// ==================== 输入验证 ====================

/**
 * 输入验证规则
 * @description 定义各种输入类型的验证规则
 */
export const VALIDATION_RULES = {
    // 用户名验证
    username: {
        pattern: /^[a-zA-Z0-9_]{3,20}$/,
        message: '用户名只能包含字母、数字和下划线，长度3-20位'
    },
    // 密码验证
    password: {
        pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d@$!%*?&]{8,}$/,
        message: '密码必须包含大小写字母和数字，长度至少8位'
    },
    // 邮箱验证
    email: {
        pattern: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
        message: '请输入有效的邮箱地址'
    },
    // 手机号验证
    phone: {
        pattern: /^1[3-9]\d{9}$/,
        message: '请输入有效的手机号码'
    },
    // 网站URL验证
    website: {
        pattern: /^https?:\/\/[^\s/$.?#].[^\s]*$/i,
        message: '请输入有效的网站地址'
    }
}

/**
 * 验证输入内容
 * @param value 需要验证的值
 * @param rule 验证规则名称或自定义规则
 * @returns 验证结果对象
 * @example
 * const result = validateField('user123', 'username')
 * // 返回: { isValid: true, message: '' }
 */
export const validateField = (
    value: string,
    rule: keyof typeof VALIDATION_RULES | RegExp | ((value: string) => boolean)
): { isValid: boolean; message: string } => {
    if (!value || typeof value !== 'string') {
        return { isValid: false, message: '输入不能为空' }
    }

    let pattern: RegExp
    let message: string

    if (typeof rule === 'string') {
        const ruleConfig = VALIDATION_RULES[rule]
        if (!ruleConfig) {
            return { isValid: false, message: '未知的验证规则' }
        }
        pattern = ruleConfig.pattern
        message = ruleConfig.message
    } else if (rule instanceof RegExp) {
        pattern = rule
        message = '输入格式不正确'
    } else if (typeof rule === 'function') {
        const isValid = rule(value)
        return { isValid, message: isValid ? '' : '输入格式不正确' }
    } else {
        return { isValid: false, message: '无效的验证规则' }
    }

    const isValid = pattern.test(value)
    return { isValid, message: isValid ? '' : message }
}

// ==================== 安全工具函数 ====================

/**
 * 生成安全的随机字符串
 * @param length 字符串长度
 * @returns 随机字符串
 * @example
 * const randomStr = generateSecureRandom(16)
 * // 返回: 'a1b2c3d4e5f6g7h8'
 */
export const generateSecureRandom = (length: number = 16): string => {
    const array = new Uint8Array(length)
    crypto.getRandomValues(array)
    return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('').slice(0, length)
}

/**
 * 安全的JSON解析
 * @param jsonString JSON字符串
 * @returns 解析后的对象，解析失败返回null
 * @example
 * const data = safeJsonParse('{"name": "test"}')
 * // 返回: { name: 'test' }
 */
export const safeJsonParse = (jsonString: string): any => {
    try {
        return JSON.parse(jsonString)
    } catch {
        return null
    }
}

/**
 * 安全的深度克隆对象
 * @param obj 需要克隆的对象
 * @returns 克隆后的对象
 * @example
 * const cloned = safeDeepClone({ name: 'test', data: [1, 2, 3] })
 */
export const safeDeepClone = <T>(obj: T): T => {
    if (obj === null || typeof obj !== 'object') {
        return obj
    }

    if (obj instanceof Date) {
        return new Date(obj.getTime()) as T
    }

    if (obj instanceof Array) {
        return obj.map(item => safeDeepClone(item)) as T
    }

    if (typeof obj === 'object') {
        const cloned = {} as T
        for (const key in obj) {
            if (obj.hasOwnProperty(key)) {
                cloned[key] = safeDeepClone(obj[key])
            }
        }
        return cloned
    }

    return obj
}

/**
 * 检查是否为安全的文件类型
 * @param filename 文件名
 * @param allowedTypes 允许的文件类型数组
 * @returns 是否为安全文件类型
 * @example
 * const isSafe = isSafeFileType('image.jpg', ['jpg', 'png', 'gif'])
 * // 返回: true
 */
export const isSafeFileType = (filename: string, allowedTypes: string[]): boolean => {
    if (!filename) {
        return false
    }

    const extension = filename.split('.').pop()?.toLowerCase()
    return extension ? allowedTypes.includes(extension) : false
}

/**
 * 获取安全的文件名
 * @param filename 原始文件名
 * @returns 安全的文件名
 * @example
 * const safeName = getSafeFilename('../../../etc/passwd')
 * // 返回: 'passwd'
 */
export const getSafeFilename = (filename: string): string => {
    if (!filename) {
        return ''
    }

    // 移除路径遍历攻击
    const cleanName = filename.replace(/\.\./g, '').replace(/[\/\\]/g, '')

    // 只保留字母、数字、下划线、连字符和点
    return cleanName.replace(/[^a-zA-Z0-9._-]/g, '')
}

// ==================== 导出 ====================

export default {
    // XSS防护
    sanitizeHtml,
    validateInput,
    escapeHtml,
    validateUrl,
    validateEmail,

    // CSRF防护
    csrfProtection,
    addCSRFToken,

    // 输入验证
    VALIDATION_RULES,
    validateField,

    // 安全工具
    generateSecureRandom,
    safeJsonParse,
    safeDeepClone,
    isSafeFileType,
    getSafeFilename
}
